<?php
namespace app\api\controller;

use think\Db;
use think\Controller;
use think\Request;
use app\superadmin\model\User as userModel;
use app\superadmin\model\Order as OrderModel;




class Wjwxpay extends controller
{

    private $appid       = "wx6b0bc166ece6d3ea";                                                        //小程序ID
    private $mch_id      = "1610714247";                                                                //商户号
    private $key         = "nqfxiu9pomyjytkvctruv2o42r84g2ao";                                          //支付secret
    private $body        = "中检集团";                                                                  //商品描述
    private $notify_url  = "https://zjyz.ccicgdauto.com/api/wjwxpay/notifyFunc";    //微信支付回调路径
	


		//微信支付接口
	public function payFunc() {

    	$uid = input("post.uid");
    	$oid = input("post.oid");

    	$userInfo = userModel::get($uid);

    	if (!$userInfo) {
    		echo json_encode(array('status' => 0, 'err' => '未知用户！'));
            exit();
    	}


    	$oInfo = OrderModel::where('id',$oid)->where('uid',$uid)->find();

    	if (!$oInfo) {
    		echo json_encode(array('status' => 0, 'err' => '未知数据！'));
            exit();
    	}

       
    	$openid = $userInfo['openid'];

    	$num = $oInfo['deposit'];

        $code = $oInfo['code'];

		
		//统一下单接口
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $parameters = array(
                    'appid' => $this->appid, //小程序ID
                    'mch_id' => $this->mch_id, //商户号
                    'nonce_str' => $this->createNoncestr(), //随机字符串
                    'body' => $this->body,
                    'out_trade_no' => $code, //商户订单号
                    'total_fee' => floatval($num*100), //总金额 单位 分
                    'spbill_create_ip' => '192.168.0.161', //终端IP
                    'notify_url' => $this->notify_url, //通知地址  确保外网能正常访问
                    'openid' => $openid, //用户id
                    'trade_type' => 'JSAPI'//交易类型
        );

        //halt($parameters);
        $parameters['sign'] = $this->getSign($parameters);//统一下单签名
        //halt($parameters['sign']);
        $xmlData = $this->arrayToXml($parameters);
        //halt($xmlData);
        $unifiedorderReturn = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));//统一下单返回数据

        //halt($unifiedorderReturn);
        
        $resultParameters = array(
                    'appId' => $this->appid, //小程序ID
                    'timeStamp' => '' . time() . '', //时间戳
                    'nonceStr' => $this->createNoncestr(), //随机串
                    'package' => 'prepay_id=' . $unifiedorderReturn['prepay_id'], //数据包
                    'signType' => 'MD5'//签名方式               
        );
        //签名
        $resultParameters['paySign'] = $this->getSign($resultParameters);
		$resultParameters['code'] = $code;
		echo json_encode(array('status'=>1,'data'=>$resultParameters));			
	}

    
			
    //微信支付回调接口  
    public function notifyFunc() {

        $postXml = file_get_contents("php://input");//接收微信参数
        if (empty($postXml)) {
            return false;
        }
        $attr        = $this->xmlToArray($postXml);
        $num         = $attr["total_fee"] / 100;
        $openid      = $attr["openid"];
        $code        = $attr["out_trade_no"];
        $time        = $attr["time_end"];
        //查询用户id
        $uInfo = userModel::where('openid',$openid)->find();      
        if(!$uInfo){
            //不存在该用户,返回错误!
            return 0;
        }
        $result = $this->wxOrderHander($uInfo['id'],$code,$num);
    
        if($result){
            $xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg>";
            $xml.="</xml>";
            echo $xml;
        }else {
            echo 'fail';
        }   
        
    }   





public function wxOrderHander($uid,$code,$num){

		  $orderinfo = OrderModel::where('code',$code)->where('uid',$uid)->where('deposit',$num)->find();
          //halt($orderinfo['status']);

          if (!$orderinfo) {
            echo '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>';
                return;
                exit();
          }

          if ($orderinfo['status'] == 2) {
            echo '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>';
                return;
                exit();
          }


          //订单状态改为已付款
          OrderModel::where('id',$orderinfo['id'])->update(['status'=>2]);

          return '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>';
          exit();

	}





		
			
	//***************************************************************************************************************************************************************************
	//分割线
	//***************************************************************************************************************************************************************************
	
			
			
			
	//****************************************
	//此处部分为业务处理操作,外部不可访问,只需写操作即可
	//****************************************			
			
		
	
	
			
	//***************************************************************************************************************************************************************************
	//分割线
	//***************************************************************************************************************************************************************************
			
	
	 //****************************************
    //此处部分为公用方法，不用做修改
    //****************************************
    //上个方法中用到的curl_post_ssl()
    public function curl_post_ssl($url, $vars, $second = 30, $aHeader = array())
    {

        $isdir = $_SERVER['DOCUMENT_ROOT'] . "/cert/"; //证书位置

        $ch = curl_init(); //初始化curl

        curl_setopt($ch, CURLOPT_TIMEOUT, $second); //设置执行最长秒数
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_URL, $url); //抓取指定网页
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 终止从服务端进行验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); //证书类型
        curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem'); //证书位置
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); //CURLOPT_SSLKEY中规定的私钥的加密类型
        curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem'); //证书位置
        curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
        //      curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');
        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader); //设置头部
        }
        curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $vars); //全部数据使用HTTP协议中的"POST"操作来发送

        $data = curl_exec($ch); //执行回话
        if ($data) {
            curl_close($ch);

            return $data;
        } else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return false;
        }
    }		
			
			
    //****************************************
    //此处部分为公用方法，不用做修改
    //****************************************	
    	
		 //xmlPost方法(固定勿动)
    private static function postXmlCurl($xml, $url, $second = 30)
        {
            $ch = curl_init();
            //设置超时
            curl_setopt($ch, CURLOPT_TIMEOUT, $second);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
            //设置header
            curl_setopt($ch, CURLOPT_HEADER, FALSE);
            //要求结果为字符串且输出到屏幕上
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            //post提交方式
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    
    
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
            curl_setopt($ch, CURLOPT_TIMEOUT, 40);
            set_time_limit(0);
    
    
            //运行curl
            $data = curl_exec($ch);
            //返回结果
            if ($data) {
                curl_close($ch);
                return $data;
            } else {
                $error = curl_errno($ch);
                curl_close($ch);
                throw new WxPayException("curl出错，错误码:$error");
            }
        }
    

		    //作用：生成签名
     private function getSign($Obj) {
        foreach ($Obj as $k => $v) {
        		$Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //签名步骤二：在string后加入KEY
        $String = $String . "&key=" . $this->key;
        //签名步骤三：MD5加密
        $String = md5($String);
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;
    }
    
    
         //数组转换成xml
    private function arrayToXml($arr) {
            $xml = "<root>";
            foreach ($arr as $key => $val) {
                if (is_array($val)) {
                    $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
                } else {
                    $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
                }
            }
            $xml .= "</root>";
            return $xml;
        }
    
    
         //xml转换成数组
    private function xmlToArray($xml) {
    
    
            //禁止引用外部xml实体
    
    
            libxml_disable_entity_loader(true);
    
    
            $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
    
    
            $val = json_decode(json_encode($xmlstring), true);
    
    
            return $val;
        }
    
    
         //作用：产生随机字符串，不长于32位
     private function createNoncestr($length = 32) {
            $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
            return $str;
        }
    
    
        ///作用：格式化参数，签名过程需要使用
     private function formatBizQueryParaMap($paraMap, $urlencode) {
          $buff = "";
          ksort($paraMap);
          foreach ($paraMap as $k => $v) {
          		if ($urlencode) {
          				$v = urlencode($v);
          		}
          		$buff .= $k . "=" . $v . "&";
          }
          $reqPar = "";
          if (strlen($buff) > 0) {
          		$reqPar = substr($buff, 0, strlen($buff) - 1);
          }
          return $reqPar;
        }
    
}


	